package ar.com.photo_admin.domain

import org.grails.plugins.imagetools.ImageTool
import org.springframework.dao.DataIntegrityViolationException

import javax.servlet.http.HttpServletResponse
import grails.plugins.springsecurity.Secured

import grails.converters.*

@Secured(["isAuthenticated()"])
class UserController {
	
    static allowedMethods = [save: "POST", update: "POST", delete: "POST", changeProfileImage: "POST"]

	final int PROFILE_IMAGE_SIZE = 210
	
	def springSecurityService
	
	def facebookService
	
	def simpleCaptchaService

	def userService
	
	def messageService
		
	def index() {
		redirect(action: "show", params: params)
	}
	
	def show() {
		User user = springSecurityService.currentUser
		[user: user]
	}
	
	def publicProfile() {
		
		User user = User.get(params.id)
		
		if (!user) {
			flash.error = message(code: 'user.no.exist')
			redirect(action: "show")
			return
		}
		
		[user: user]
	}
	
	def saveProfile() {
		User user = springSecurityService.currentUser
		
		user.properties = params
		user.captchaCode = params.captchaCode
		
		user.validate()
		boolean captchaValid = validateCaptcha(user)
						
		if (captchaValid && userService.save(user)) {
			flash.message = message(code: 'user.profile.update')
			redirect(action: "show")
		} else {
			user.captchaCode = ""
			render(view: "show", model: [user: user])			
		}				
	}
	
	def changePassword() {
		User user = springSecurityService.currentUser
		
		/*
		 * The user must have a password to be able to change it.
		 */
		if (user.password) {
			def oldPassword = springSecurityService.encodePassword(params.oldPassword)
			def newPassword = springSecurityService.encodePassword(params.password)
			/*
			 * Checks if the password is correct.
			 */
			if (!user.password.equals(oldPassword)) {
				user.errors.rejectValue("oldPassword", "user.profile.change.password.invalid")
				render(template: "changePassword", model: [user: user])
			} 				
			/*
			 * New password must be be different from the previous one.
			 */
			else if (oldPassword.equals(newPassword)) {
				user.errors.rejectValue("oldPassword", "user.profile.change.password.invalid2")
				render(template: "changePassword", model: [user: user])
			}			
			else {
				_changePassword(user, "changePassword", "user.profile.change.password.message")
			}
			
		} else
			render Utils.RELOAD_PAGE_ON_AJAX_RESPONSE
	}

	def generatePassword() {
		User user = springSecurityService.currentUser
		
		/*
		 * The user must not have a password to be able to generate one.
		 */
		if (!user.password)
			_changePassword(user, "generatePassword", "user.profile.generate.password.message")
		else
			render Utils.RELOAD_PAGE_ON_AJAX_RESPONSE
	}
	
	def _changePassword(User user, String templateId, String successMessageCode) {
		
		user.password = params.password
		user.confirmPassword = params.confirmPassword
			
		if (userService.save(user)) {
			springSecurityService.reauthenticate(user.username)
			flash.message = message(code: successMessageCode)
			render Utils.RELOAD_PAGE_ON_AJAX_RESPONSE
		}
		else
			render(template: templateId, model: [user: user])	
	}
	
	def detachFacebookAccount() {
		
		User user = springSecurityService.currentUser
					
		/*
		 * Cannot detach if the user is not logged in with facebook.
		 */
		if (!user.facebookUid) 
			flash.error = message(code: "user.profile.social.networks.facebook.detach.fail.facebook")
		/*
		 * Before detaching, the user must generate a password to be able to log in to the site.
		 */
		else if (!user.password) {
			flash.error = message(code: "user.profile.social.networks.facebook.detach.fail.password")
		} else {
			user.facebookUid = null
			user.useFacebookProfileImage = false
					
			if (userService.save(user)) {
				springSecurityService.reauthenticate(user.username)
				session.facebook = null
				flash.message = message(code: "user.profile.social.networks.facebook.detach.success")
			}
		}			

		redirect(action: "show")
	}
	
	def attachFacebookAccount() {
		
		User user = springSecurityService.currentUser
		def profile = facebookService.getProfileByFacebookUidUsingSession()

		/*
		 * Only one facebook account per user is allowed.		
		 */
		if (user.facebookUid) {
			session.facebook = null
			flash.error = message(code: "user.profile.social.networks.facebook.attach.fail.facebook")
		}
		else if (facebookService.isUserRegistered(profile.id)) {
			session.facebook = null
			flash.error = message(code: "user.facebookUid.unique")
		} else {
			user.facebookUid = profile.id
					
			if (userService.save(user))
				flash.message = message(code: "user.profile.social.networks.facebook.attach.success")
		}

		redirect(action: "show")	
	}
	
	def uploadProfileImage() {
		
		User user = springSecurityService.currentUser
		
		def image = request.getFile('imageFile')
		def okContents = ['image/png', 'image/jpeg', 'image/gif']
		
		if (!image.empty && !okContents.contains(image.getContentType()))
			flash.error = message(code: "user.profile.image.invalid.extension")
		else {
		
			try {
				ImageTool imageTool = new ImageTool()
				imageTool.load(image.getBytes())
				imageTool.square()
				imageTool.swapSource()
				imageTool.thumbnail(PROFILE_IMAGE_SIZE)
				
				user.profileImage = imageTool.getBytes("JPEG")
				user.profileImageType = 'image/jpeg'

				boolean useFacebook = user.useFacebookProfileImage;
				if (useFacebook)
					user.useFacebookProfileImage = false
				
				if (userService.save(user)) {
					if (useFacebook)
						flash.message = message(code: "user.profile.image.facebook.unchecked2")
					else
						flash.message = message(code: "user.profile.image.update.success")					
				} else
					flash.error = message(code: "user.profileImage.maxSize.exceeded")					
			} catch (Exception e) {
				flash.error = message(code: "user.profile.image.invalid.damage")
			}
		}
						
		redirect(action: "show")
	}
	
	def profileImage = {
		
		User user = User.get(params.id)
		
		if (user.useFacebookProfileImage) {
			def imageUrl = facebookService.getProfilePhotoSrc(user.facebookUid) + "?type=large"
			redirect(url : imageUrl)
		}		
		else if (user.profileImageType && user.profileImage) {
			response.setContentType(user.profileImageType)
			response.setContentLength(user.profileImage.size())
			OutputStream out = response.getOutputStream();
			out.write(user.profileImage);
			out.close();
					
		} else {
			def defaultImageUrl = "/images/defaultImage.jpg"
			redirect(url : defaultImageUrl)
		}
	}
	
	def useFacebookProfileImage() {
		
		User user = springSecurityService.currentUser
		
		if (user.facebookUid) {
			
			user.useFacebookProfileImage = !user.useFacebookProfileImage
			
			if (userService.save(user)) {
				if (user.useFacebookProfileImage)
					flash.message = message(code: "user.profile.image.facebook.checked")
				else
					flash.message = message(code: "user.profile.image.facebook.unchecked")
			} else
				flash.error = message(code: "user.profile.image.facebook.fail")
		} else 
			flash.error = message(code: "user.profile.image.facebook.fail2")
		
		redirect(action: "show")
	}
	
	def validateCaptcha(User user) {
		
		boolean captchaValid = simpleCaptchaService.validateCaptcha(user.captchaCode)
		
		if (!captchaValid)
			user.errors.rejectValue("captchaCode", "user.captcha.invalid")
		
		return captchaValid
	}
	
	def autocompleteUser(){						
		render userService.autocompleteUser(params.term)
	}
	
	def sendMessage() {
		
		String subject = params.subject
		String body = params.message
		
		User from = springSecurityService.currentUser
		User to = User.get(params.to_user_id)
		
		def sendMessage = messageService.sendMessage(subject, body, from, to)
		
		flash.message = message(code: "messages.sent.success")
		
		redirect(controller: "message", action: "show", id: sendMessage.id)
	}
}
